﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.ComponentModel.Design.Serialization
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports System.Globalization
Imports System.IO
Imports System.Runtime.CompilerServices
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Serialization
Imports System.Workflow.Runtime
Imports System.Xml

Namespace System.Workflow.Runtime.Tracking
    Public Class SqlTrackingWorkflowInstance
        ' Methods
        Private Sub New()
            Me._currDT = DateTime.UtcNow
            Me._actMinDT = SqlDateTime.MinValue.Value
            Me._userMinDT = SqlDateTime.MinValue.Value
            Me._instMinDT = SqlDateTime.MinValue.Value
            Me._childMinDT = SqlDateTime.MinValue.Value
            Me._changesMinDT = SqlDateTime.MinValue.Value
            Me._invMinDT = SqlDateTime.MinValue.Value
            Me._internalId = -1
            Me._invoker = Guid.Empty
            Me._activityEvents = New List([Of] ActivityTrackingRecord)
            Me._userEvents = New List([Of] UserTrackingRecord)
            Me._workflowEvents = New List([Of] WorkflowTrackingRecord)
            Me._invoked = New List([Of] SqlTrackingWorkflowInstance)
        End Sub

        Friend Sub New(ByVal connectionString As String)
            Me._currDT = DateTime.UtcNow
            Me._actMinDT = SqlDateTime.MinValue.Value
            Me._userMinDT = SqlDateTime.MinValue.Value
            Me._instMinDT = SqlDateTime.MinValue.Value
            Me._childMinDT = SqlDateTime.MinValue.Value
            Me._changesMinDT = SqlDateTime.MinValue.Value
            Me._invMinDT = SqlDateTime.MinValue.Value
            Me._internalId = -1
            Me._invoker = Guid.Empty
            Me._activityEvents = New List([Of] ActivityTrackingRecord)
            Me._userEvents = New List([Of] UserTrackingRecord)
            Me._workflowEvents = New List([Of] WorkflowTrackingRecord)
            Me._invoked = New List([Of] SqlTrackingWorkflowInstance)
            If (connectionString Is Nothing) Then
                Throw New ArgumentNullException("connectionString")
            End If
            Me._connectionString = connectionString
        End Sub

        Private Function CreateInternalIdDateTimeCommand(ByVal commandText As String, ByVal minDT As DateTime) As SqlCommand
            Return Me.CreateInternalIdDateTimeCommand(commandText, minDT, Me._currDT)
        End Function

        Private Function CreateInternalIdDateTimeCommand(ByVal commandText As String, ByVal minDT As DateTime, ByVal maxDT As DateTime) As SqlCommand
            If (commandText Is Nothing) Then
                Throw New ArgumentNullException("commandText")
            End If
            Dim command As New SqlCommand { _
                .CommandType = CommandType.StoredProcedure, _
                .CommandText = commandText _
            }
            Dim parameter As New SqlParameter("@WorkflowInstanceInternalId", SqlDbType.BigInt) { _
                .Value = Me._internalId _
            }
            command.Parameters.Add(parameter)
            parameter = New SqlParameter("@BeginDateTime", SqlDbType.DateTime) { _
                .Value = minDT _
            }
            command.Parameters.Add(parameter)
            parameter = New SqlParameter("@EndDateTime", SqlDbType.DateTime) { _
                .Value = maxDT _
            }
            command.Parameters.Add(parameter)
            Return command
        End Function

        Private Sub ExecuteRetried(ByVal cmd As SqlCommand, ByVal loader As LoadFromReader)
            Me.ExecuteRetried(cmd, loader, Nothing)
        End Sub

        Private Sub ExecuteRetried(ByVal cmd As SqlCommand, ByVal loader As LoadFromReader, ByVal loadFromReaderParam As Object)
            Dim reader As SqlDataReader = Nothing
            Dim num As Short = 0
        Label_0004:
            Try 
                [Using] connection As SqlConnection = New SqlConnection(Me._connectionString)
                    cmd.Connection = connection
                    cmd.Connection.Open
                    reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
                    loader.Invoke(reader, loadFromReaderParam)
                End [Using]
            Catch exception As SqlException
                If ((SqlTrackingWorkflowInstance._deadlock <> exception.Number) OrElse (num = CShort((num + 1)) >= SqlTrackingWorkflowInstance._retries)) Then
                    Throw
                End If
                goto Label_0004
            Finally
                If ((Not reader Is Nothing) AndAlso Not reader.IsClosed) Then
                    reader.Close
                End If
            End Try
        End Sub

        Private Sub LoadActivityEvents()
            Dim cmd As SqlCommand = Me.CreateInternalIdDateTimeCommand("[dbo].[GetActivityEventsWithDetails]", Me._actMinDT)
            Me.ExecuteRetried(cmd, New LoadFromReader(AddressOf Me.LoadActivityEventsFromReader))
        End Sub

        Private Sub LoadActivityEventsFromReader(ByVal reader As SqlDataReader, ByVal parameter As Object)
            If (reader Is Nothing) Then
                Throw New ArgumentNullException("reader")
            End If
            Dim dictionary As New Dictionary([Of] Long, ActivityTrackingRecord)
            Dim time As DateTime = SqlDateTime.MinValue.Value
            Do While reader.Read
                Dim qualifiedName As String = reader.GetString(0)
                Dim executionStatus As ActivityExecutionStatus = DirectCast(reader.Item(1), ActivityExecutionStatus)
                Dim dateTime As DateTime = reader.GetDateTime(2)
                Dim contextGuid As Guid = reader.GetGuid(3)
                Dim guid As Guid = reader.GetGuid(4)
                Dim eventOrder As Integer = reader.GetInt32(5)
                If (reader.IsDBNull(6) OrElse reader.IsDBNull(7)) Then
                    Throw New InvalidOperationException(String.Format(CultureInfo.CurrentCulture, ExecutionStringManager.SqlTrackingTypeNotFound, New Object() { qualifiedName }))
                End If
                Dim activityType As Type = Type.GetType((reader.GetString(6) & ", " & reader.GetString(7)), True, False)
                Dim key As Long = reader.GetInt64(8)
                Dim time3 As DateTime = reader.GetDateTime(9)
                dictionary.Add(key, New ActivityTrackingRecord(activityType, qualifiedName, contextGuid, guid, executionStatus, dateTime, eventOrder, Nothing))
                If (time3 > time) Then
                    time = time3
                End If
            Loop
            If Not reader.NextResult Then
                Throw New ArgumentException(ExecutionStringManager.InvalidActivityEventReader)
            End If
            Do While reader.Read
                Dim num3 As Long = reader.GetInt64(0)
                Dim str2 As String = Nothing
                If Not reader.IsDBNull(1) Then
                    str2 = reader.GetString(1)
                End If
                Dim record As ActivityTrackingRecord = Nothing
                If (dictionary.TryGetValue(num3, record) AndAlso (Not record Is Nothing)) Then
                    record.Annotations.Add(str2)
                End If
            Loop
            If Not reader.NextResult Then
                Throw New ArgumentException(ExecutionStringManager.InvalidActivityEventReader)
            End If
            Dim formatter As New BinaryFormatter
            Dim dictionary2 As New Dictionary([Of] Long, TrackingDataItem)
            Do While reader.Read
                Dim num4 As Long = reader.GetInt64(0)
                Dim num5 As Long = reader.GetInt64(1)
                Dim str3 As String = reader.GetString(2)
                Dim str4 As String = Nothing
                Dim obj2 As Object = Nothing
                If Not reader.IsDBNull(3) Then
                    str4 = reader.GetString(3)
                End If
                If Not reader.IsDBNull(4) Then
                    obj2 = formatter.Deserialize(New MemoryStream(DirectCast(reader.Item(4), Byte())))
                End If
                Dim item As New TrackingDataItem { _
                    .FieldName = str3 _
                }
                If (Not obj2 Is Nothing) Then
                    item.Data = obj2
                Else
                    item.Data = str4
                End If
                dictionary2.Add(num5, item)
                Dim record2 As ActivityTrackingRecord = Nothing
                If (dictionary.TryGetValue(num4, record2) AndAlso (Not record2 Is Nothing)) Then
                    record2.Body.Add(item)
                End If
            Loop
            If Not reader.NextResult Then
                Throw New ArgumentException(ExecutionStringManager.InvalidActivityEventReader)
            End If
            Do While reader.Read
                Dim num6 As Long = reader.GetInt64(0)
                Dim str5 As String = Nothing
                If Not reader.IsDBNull(1) Then
                    str5 = reader.GetString(1)
                End If
                Dim item2 As TrackingDataItem = Nothing
                If (dictionary2.TryGetValue(num6, item2) AndAlso (Not item2 Is Nothing)) Then
                    item2.Annotations.Add(str5)
                End If
            Loop
            Me._activityEvents.AddRange(dictionary.Values)
            If (time > SqlDateTime.MinValue.Value) Then
                Me._actMinDT = time
            End If
        End Sub

        Private Sub LoadChangesFromReader(ByVal reader As SqlDataReader, ByVal parameter As Object)
            If reader.Read Then
                Dim dateTime As DateTime = Me._changesMinDT
                If Not reader.IsDBNull(0) Then
                    dateTime = reader.GetDateTime(0)
                End If
                If reader.NextResult Then
                    Dim serializer As New WorkflowMarkupSerializer
                    Dim serializationManager As New DesignerSerializationManager
                    Do While reader.Read
                        [Using] reader2 As StringReader = New StringReader(reader.GetString(0))
                            [Using] serializationManager.CreateSession
                                [Using] reader3 As XmlReader = XmlReader.Create(reader2)
                                    Dim action As ActivityChangeAction = [TryCast](serializer.Deserialize(serializationManager, reader3),ActivityChangeAction)
                                    Dim errors As IList = serializationManager.Errors
                                    If (action Is Nothing) Then
                                        Throw New WorkflowMarkupSerializationException(ExecutionStringManager.WorkflowMarkupDeserializationError)
                                    End If
                                    action.ApplyTo(Me._def)
                                    [Continue] Do
                                End [Using]
                            End [Using]
                        End [Using]
                    Loop
                End If
                If (dateTime > Me._changesMinDT) Then
                    Me._changed = True
                    Me._changesMinDT = dateTime
                End If
            End If
        End Sub

        Private Sub LoadDef()
            Dim cmd As SqlCommand = Nothing
            If (Me._def Is Nothing) Then
                cmd = New SqlCommand { _
                    .CommandType = CommandType.StoredProcedure, _
                    .CommandText = "[dbo].[GetWorkflowDefinition]" _
                }
                cmd.Parameters.Add(New SqlParameter("@WorkflowInstanceInternalId", Me._internalId))
                Me.ExecuteRetried(cmd, New LoadFromReader(AddressOf Me.LoadDefFromReader))
            End If
            cmd = Me.CreateInternalIdDateTimeCommand("[dbo].[GetWorkflowChanges]", Me._changesMinDT)
            Me.ExecuteRetried(cmd, New LoadFromReader(AddressOf Me.LoadChangesFromReader))
        End Sub

        Private Sub LoadDefFromReader(ByVal reader As SqlDataReader, ByVal parameter As Object)
            If (reader Is Nothing) Then
                Throw New ArgumentNullException("reader")
            End If
            If Not reader.Read Then
                Throw New ArgumentException(ExecutionStringManager.InvalidDefinitionReader)
            End If
            Dim input As New StringReader(reader.GetString(0))
            Dim serializer As New WorkflowMarkupSerializer
            Dim serializationManager As New DesignerSerializationManager
            Dim errors As IList = Nothing
            Try 
                [Using] serializationManager.CreateSession
                    [Using] reader3 As XmlReader = XmlReader.Create(input)
                        Me._def = [TryCast](serializer.Deserialize(serializationManager, reader3),Activity)
                        errors = serializationManager.Errors
                    End [Using]
                End [Using]
            Finally
                input.Close
            End Try
            If ((Me._def Is Nothing) OrElse ((Not errors Is Nothing) AndAlso (errors.Count > 0))) Then
                Throw New WorkflowMarkupSerializationException(ExecutionStringManager.WorkflowMarkupDeserializationError)
            End If
        End Sub

        Private Sub LoadInvokedWorkflows()
            Dim cmd As New SqlCommand { _
                .CommandText = "[dbo].[GetInvokedWorkflows]", _
                .CommandType = CommandType.StoredProcedure _
            }
            Dim parameter As New SqlParameter("@WorkflowInstanceId", SqlDbType.UniqueIdentifier) { _
                .Value = Me._id _
            }
            cmd.Parameters.Add(parameter)
            parameter = New SqlParameter("@BeginDateTime", SqlDbType.DateTime) { _
                .Value = Me._invMinDT _
            }
            cmd.Parameters.Add(parameter)
            parameter = New SqlParameter("@EndDateTime", SqlDbType.DateTime) { _
                .Value = Me._currDT _
            }
            cmd.Parameters.Add(parameter)
            Me.ExecuteRetried(cmd, New LoadFromReader(AddressOf Me.LoadInvokedWorkflowsFromReader))
        End Sub

        Private Sub LoadInvokedWorkflowsFromReader(ByVal reader As SqlDataReader, ByVal parameter As Object)
            If (reader Is Nothing) Then
                Throw New ArgumentNullException("reader")
            End If
            Dim initialized As DateTime = SqlDateTime.MinValue.Value
            Do While reader.Read
                Dim item As SqlTrackingWorkflowInstance = SqlTrackingQuery.BuildInstance(reader, Me._connectionString)
                If (item.Initialized > initialized) Then
                    initialized = item.Initialized
                End If
                Me._invoked.Add(item)
            Loop
            If (initialized > SqlDateTime.MinValue.Value) Then
                Me._invMinDT = initialized
            End If
        End Sub

        Private Sub LoadUserEvents()
            Dim cmd As SqlCommand = Me.CreateInternalIdDateTimeCommand("[dbo].[GetUserEventsWithDetails]", Me._userMinDT)
            Me.ExecuteRetried(cmd, New LoadFromReader(AddressOf Me.LoadUserEventsFromReader))
        End Sub

        Private Sub LoadUserEventsFromReader(ByVal reader As SqlDataReader, ByVal parameter As Object)
            If (reader Is Nothing) Then
                Throw New ArgumentNullException("reader")
            End If
            Dim formatter As New BinaryFormatter
            Dim dictionary As New Dictionary([Of] Long, UserTrackingRecord)
            Dim time As DateTime = SqlDateTime.MinValue.Value
            Do While reader.Read
                Dim qualifiedName As String = reader.GetString(0)
                Dim dateTime As DateTime = reader.GetDateTime(1)
                Dim contextGuid As Guid = reader.GetGuid(2)
                Dim guid As Guid = reader.GetGuid(3)
                Dim eventOrder As Integer = reader.GetInt32(4)
                Dim userDataKey As String = Nothing
                If Not reader.IsDBNull(5) Then
                    userDataKey = reader.GetString(5)
                End If
                Dim userData As Object = Nothing
                If Not reader.IsDBNull(7) Then
                    userData = formatter.Deserialize(New MemoryStream(DirectCast(reader.Item(7), Byte())))
                ElseIf Not reader.IsDBNull(6) Then
                    userData = reader.GetString(6)
                End If
                If (reader.IsDBNull(8) OrElse reader.IsDBNull(9)) Then
                    Throw New InvalidOperationException(String.Format(CultureInfo.CurrentCulture, ExecutionStringManager.SqlTrackingTypeNotFound, New Object() { qualifiedName }))
                End If
                Dim activityType As Type = Type.GetType((reader.GetString(8) & ", " & reader.GetString(9)), True, False)
                Dim key As Long = reader.GetInt64(10)
                Dim time3 As DateTime = reader.GetDateTime(11)
                dictionary.Add(key, New UserTrackingRecord(activityType, qualifiedName, contextGuid, guid, dateTime, eventOrder, userDataKey, userData))
                If (time3 > time) Then
                    time = time3
                End If
            Loop
            If Not reader.NextResult Then
                Throw New ArgumentException(ExecutionStringManager.InvalidUserEventReader)
            End If
            Do While reader.Read
                Dim num3 As Long = reader.GetInt64(0)
                Dim str3 As String = Nothing
                If Not reader.IsDBNull(1) Then
                    str3 = reader.GetString(1)
                End If
                Dim record As UserTrackingRecord = Nothing
                If (dictionary.TryGetValue(num3, record) AndAlso (Not record Is Nothing)) Then
                    record.Annotations.Add(str3)
                End If
            Loop
            If Not reader.NextResult Then
                Throw New ArgumentException(ExecutionStringManager.InvalidUserEventReader)
            End If
            Dim dictionary2 As New Dictionary([Of] Long, TrackingDataItem)
            Do While reader.Read
                Dim num4 As Long = reader.GetInt64(0)
                Dim num5 As Long = reader.GetInt64(1)
                Dim str4 As String = reader.GetString(2)
                Dim str5 As String = Nothing
                Dim obj3 As Object = Nothing
                If Not reader.IsDBNull(3) Then
                    str5 = reader.GetString(3)
                End If
                If Not reader.IsDBNull(4) Then
                    obj3 = formatter.Deserialize(New MemoryStream(DirectCast(reader.Item(4), Byte())))
                End If
                Dim item As New TrackingDataItem { _
                    .FieldName = str4 _
                }
                If (Not obj3 Is Nothing) Then
                    item.Data = obj3
                Else
                    item.Data = str5
                End If
                dictionary2.Add(num5, item)
                Dim record2 As UserTrackingRecord = Nothing
                If (dictionary.TryGetValue(num4, record2) AndAlso (Not record2 Is Nothing)) Then
                    record2.Body.Add(item)
                End If
            Loop
            If Not reader.NextResult Then
                Throw New ArgumentException(ExecutionStringManager.InvalidUserEventReader)
            End If
            Do While reader.Read
                Dim num6 As Long = reader.GetInt64(0)
                Dim str6 As String = Nothing
                If Not reader.IsDBNull(1) Then
                    str6 = reader.GetString(1)
                End If
                Dim item2 As TrackingDataItem = Nothing
                If (dictionary2.TryGetValue(num6, item2) AndAlso (Not item2 Is Nothing)) Then
                    item2.Annotations.Add(str6)
                End If
            Loop
            Me._userEvents.AddRange(dictionary.Values)
            If (time > SqlDateTime.MinValue.Value) Then
                Me._userMinDT = time
            End If
        End Sub

        Private Sub LoadWorkflowChangeEventArgsFromReader(ByVal reader As SqlDataReader, ByVal parameter As Object)
            If (reader Is Nothing) Then
                Throw New ArgumentNullException("reader")
            End If
            If (parameter Is Nothing) Then
                Throw New ArgumentNullException("parameter")
            End If
            Dim record As WorkflowTrackingRecord = [TryCast](parameter,WorkflowTrackingRecord)
            If (record Is Nothing) Then
                Throw New ArgumentException(ExecutionStringManager.InvalidWorkflowChangeEventArgsParameter, "parameter")
            End If
            If Not reader.Read Then
                Throw New ArgumentException(ExecutionStringManager.InvalidWorkflowChangeEventArgsReader)
            End If
            Dim input As New StringReader(reader.GetString(0))
            Dim rootActivity As Activity = Nothing
            Dim serializer As New WorkflowMarkupSerializer
            Dim serializationManager As New DesignerSerializationManager
            Dim errors As IList = Nothing
            Try 
                [Using] serializationManager.CreateSession
                    [Using] reader3 As XmlReader = XmlReader.Create(input)
                        rootActivity = [TryCast](serializer.Deserialize(serializationManager, reader3),Activity)
                        errors = serializationManager.Errors
                    End [Using]
                End [Using]
            Finally
                input.Close
            End Try
            If ((rootActivity Is Nothing) OrElse ((Not errors Is Nothing) AndAlso (errors.Count > 0))) Then
                Throw New WorkflowMarkupSerializationException(ExecutionStringManager.WorkflowMarkupDeserializationError)
            End If
            If Not reader.NextResult Then
                Throw New ArgumentException(ExecutionStringManager.InvalidWorkflowChangeEventArgsReader)
            End If
            If Not reader.NextResult Then
                Throw New ArgumentException(ExecutionStringManager.InvalidWorkflowChangeEventArgsReader)
            End If
            Dim changes As New List([Of] WorkflowChangeAction)
            Dim minValue As DateTime = DateTime.MinValue
            Dim num As Integer = -1
            Do While reader.Read
                Dim dateTime As DateTime = reader.GetDateTime(1)
                Dim num2 As Integer = reader.GetInt32(2)
                Dim num3 As Integer = reader.GetInt32(3)
                If ((dateTime > minValue) AndAlso (num2 > num)) Then
                    num = num2
                    minValue = dateTime
                    changes = New List([Of] WorkflowChangeAction)
                End If
                [Using] input = New StringReader(reader.GetString(0))
                    [Using] serializationManager.CreateSession
                        [Using] reader4 As XmlReader = XmlReader.Create(input)
                            Dim item As ActivityChangeAction = [TryCast](serializer.Deserialize(serializationManager, reader4),ActivityChangeAction)
                            errors = serializationManager.Errors
                            If (item Is Nothing) Then
                                Throw New WorkflowMarkupSerializationException(ExecutionStringManager.WorkflowMarkupDeserializationError)
                            End If
                            changes.Add(item)
                            item.ApplyTo(rootActivity)
                        End [Using]
                    End [Using]
                    [Continue] Do
                End [Using]
            Loop
            record.EventArgs = New TrackingWorkflowChangedEventArgs(changes, rootActivity)
        End Sub

        Private Sub LoadWorkflowEvents()
            Dim cmd As SqlCommand = Me.CreateInternalIdDateTimeCommand("[dbo].[GetWorkflowInstanceEventsWithDetails]", Me._instMinDT)
            Me.ExecuteRetried(cmd, New LoadFromReader(AddressOf Me.LoadWorkflowEventsFromReader))
        End Sub

        Private Sub LoadWorkflowEventsFromReader(ByVal reader As SqlDataReader, ByVal parameter As Object)
            If (reader Is Nothing) Then
                Throw New ArgumentNullException("reader")
            End If
            Dim time As DateTime = SqlDateTime.MinValue.Value
            Dim dictionary As New Dictionary([Of] Long, WorkflowTrackingRecord)
            Do While reader.Read
                Dim trackingWorkflowEvent As TrackingWorkflowEvent = DirectCast(reader.Item(0), TrackingWorkflowEvent)
                Dim dateTime As DateTime = reader.GetDateTime(1)
                Dim eventOrder As Integer = reader.GetInt32(2)
                Dim obj2 As Object = Nothing
                Dim eventArgs As EventArgs = Nothing
                If Not reader.IsDBNull(3) Then
                    obj2 = New BinaryFormatter().Deserialize(New MemoryStream(DirectCast(reader.Item(3), Byte())))
                    If TypeOf obj2 Is EventArgs Then
                        eventArgs = DirectCast(obj2, EventArgs)
                    End If
                End If
                Dim key As Long = reader.GetInt64(4)
                Dim time3 As DateTime = reader.GetDateTime(5)
                dictionary.Add(key, New WorkflowTrackingRecord(trackingWorkflowEvent, dateTime, eventOrder, eventArgs))
                If (time3 > time) Then
                    time = time3
                End If
            Loop
            If Not reader.NextResult Then
                Throw New ArgumentException(ExecutionStringManager.InvalidWorkflowInstanceEventReader)
            End If
            Do While reader.Read
                Dim num3 As Long = reader.GetInt64(0)
                Dim item As String = Nothing
                If Not reader.IsDBNull(1) Then
                    item = reader.GetString(1)
                End If
                Dim record As WorkflowTrackingRecord = Nothing
                If (dictionary.TryGetValue(num3, record) AndAlso (Not record Is Nothing)) Then
                    record.Annotations.Add(item)
                End If
            Loop
            If Not reader.IsClosed Then
                reader.Close
            End If
            Dim pair As KeyValuePair([Of] Long, WorkflowTrackingRecord)
            For Each pair In dictionary
                Dim loadFromReaderParam As WorkflowTrackingRecord = pair.Value
                If (TrackingWorkflowEvent.Changed = loadFromReaderParam.TrackingWorkflowEvent) Then
                    Dim cmd As New SqlCommand { _
                        .CommandType = CommandType.StoredProcedure, _
                        .CommandText = "[dbo].[GetWorkflowChangeEventArgs]" _
                    }
                    cmd.Parameters.Add(New SqlParameter("@WorkflowInstanceInternalId", Me._internalId))
                    cmd.Parameters.Add(New SqlParameter("@BeginDateTime", SqlDateTime.MinValue.Value))
                    cmd.Parameters.Add(New SqlParameter("@WorkflowInstanceEventId", pair.Key))
                    Me.ExecuteRetried(cmd, New LoadFromReader(AddressOf Me.LoadWorkflowChangeEventArgsFromReader), loadFromReaderParam)
                End If
            Next
            Me._workflowEvents.AddRange(dictionary.Values)
            If (time > SqlDateTime.MinValue.Value) Then
                Me._instMinDT = time
            End If
        End Sub

        Public Sub Refresh()
            Me._currDT = DateTime.UtcNow
        End Sub


        ' Properties
        Public ReadOnly Property ActivityEvents As IList([Of] ActivityTrackingRecord)
            Get
                If Me._autoRefresh Then
                    Me.Refresh
                End If
                Me.LoadActivityEvents
                Return Me._activityEvents
            End Get
        End Property

        Public Property AutoRefresh As Boolean
            Get
                Return Me._autoRefresh
            End Get
            Set(ByVal value As Boolean)
                Me._autoRefresh = value
            End Set
        End Property

        Public Property Initialized As DateTime
            Get
                Return Me._initialized
            End Get
            Set(ByVal value As DateTime)
                Me._initialized = value
            End Set
        End Property

        Public ReadOnly Property InvokedWorkflows As IList([Of] SqlTrackingWorkflowInstance)
            Get
                If Me._autoRefresh Then
                    Me.Refresh
                End If
                Me.LoadInvokedWorkflows
                Return Me._invoked
            End Get
        End Property

        Public Property InvokingWorkflowInstanceId As Guid
            Get
                Return Me._invoker
            End Get
            Set(ByVal value As Guid)
                Me._invoker = value
            End Set
        End Property

        Public Property Status As WorkflowStatus
            Get
                Return Me._status
            End Get
            Set(ByVal value As WorkflowStatus)
                Me._status = value
            End Set
        End Property

        Public ReadOnly Property UserEvents As IList([Of] UserTrackingRecord)
            Get
                If Me._autoRefresh Then
                    Me.Refresh
                End If
                Me.LoadUserEvents
                Return Me._userEvents
            End Get
        End Property

        Public ReadOnly Property WorkflowDefinition As Activity
            Get
                If Me._autoRefresh Then
                    Me.Refresh
                End If
                Me.LoadDef
                Return Me._def
            End Get
        End Property

        Public ReadOnly Property WorkflowDefinitionUpdated As Boolean
            Get
                If Me._autoRefresh Then
                    Me.Refresh
                End If
                Me.LoadDef
                Return Me._changed
            End Get
        End Property

        Public ReadOnly Property WorkflowEvents As IList([Of] WorkflowTrackingRecord)
            Get
                If Me._autoRefresh Then
                    Me.Refresh
                End If
                Me.LoadWorkflowEvents
                Return Me._workflowEvents
            End Get
        End Property

        Public Property WorkflowInstanceId As Guid
            Get
                Return Me._id
            End Get
            Set(ByVal value As Guid)
                Me._id = value
            End Set
        End Property

        Public Property WorkflowInstanceInternalId As Long
            Get
                Return Me._internalId
            End Get
            Set(ByVal value As Long)
                Me._internalId = value
            End Set
        End Property

        Public Property WorkflowType As Type
            Get
                Return Me._workflowType
            End Get
            Set(ByVal value As Type)
                Me._workflowType = value
            End Set
        End Property


        ' Fields
        Private _activityEvents As List([Of] ActivityTrackingRecord)
        Private _actMinDT As DateTime
        Private _autoRefresh As Boolean
        Private _changed As Boolean
        Private _changesMinDT As DateTime
        Private _childMinDT As DateTime
        Private _connectionString As String
        Private _currDT As DateTime
        Private Shared _deadlock As Integer = &H4B5
        Private _def As Activity
        Private _id As Guid
        Private _initialized As DateTime
        Private _instMinDT As DateTime
        Private _internalId As Long
        Private _invMinDT As DateTime
        Private _invoked As List([Of] SqlTrackingWorkflowInstance)
        Private _invoker As Guid
        Private Shared _retries As Short = 5
        Private _status As WorkflowStatus
        Private _userEvents As List([Of] UserTrackingRecord)
        Private _userMinDT As DateTime
        Private _workflowEvents As List([Of] WorkflowTrackingRecord)
        Private _workflowType As Type

        ' Nested Types
        Private Delegate Sub LoadFromReader(ByVal reader As SqlDataReader, ByVal parameter As Object)
    End Class
End Namespace

